# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   File Name：     grammar
   Description :
   Author :       Flyoung
   date：          2023/4/16
-------------------------------------------------
   Change Activity:
                   2023/4/16:
-------------------------------------------------
"""
from typing import Union
from data_structure.non_terminator import NonTerminator
from data_structure.string import String
from lib import epsilon, eof


class Grammar:
    def __init__(self, productions: list[str]):
        # 文法
        self.productions = [p.replace(' ', '') for p in productions]
        self.non_terminator_list: list[NonTerminator] = list()
        self.end = '\n\n'

    def parse_productions(self) -> None:
        # 解析所有产生式
        for production in self.productions:
            left, right = production.split('->')
            non_terminator = NonTerminator(String(left))
            non_terminator.equal_list.extend([String(i) for i in right.split('|')])
            self.non_terminator_list.append(non_terminator)

    def show_non_terminator_list(self) -> None:
        # 打印所有非终结符
        for i in self.non_terminator_list:
            print(i)
        print(self.end)

    def show_first_set(self) -> None:
        # 打印 first 集合
        for non_terminator in self.non_terminator_list:
            print(non_terminator.get_first_set_str())
        print(self.end)

    def show_follow_set(self) -> None:
        # 打印 follow 集合
        for non_terminator in self.non_terminator_list:
            print(non_terminator.get_follow_set_str())
        print(self.end)

    def get_non_terminator(self, name: Union[str, String]) -> Union[NonTerminator, None]:
        # 根据非终结符获取非终结符
        for i in self.non_terminator_list:
            if i.name == name:
                return i
        return None

    def get_follow_set_size(self, name: Union[str, String]) -> int:
        # 获取非终结符的 Follow 集合大小
        return len(self.get_non_terminator(name).Follow)

    def is_non_terminator(self, string: Union[str, String]) -> bool:
        # 判断 string 是否为该文法的非终结符
        return any([
            i.name == string for i in self.non_terminator_list
        ])

    def get_input_symbols(self):
        # 获取输入符号集合
        symbols = set()
        for non_terminator in self.non_terminator_list:
            for right in non_terminator.equal_list:
                for symbol in right.split_symbol():
                    if not self.is_non_terminator(symbol) and symbol != epsilon:
                        symbols.add(symbol)
        symbols.add(eof)
        return symbols
